#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2020 OpenWrt.org
# Copyright (C) 2022 ImmortalWrt.org

START=99
USE_PROCD=1
# respawn for  a  mouth
respawn_threshold=30
respawn_timeout=5
respawn_retry=518400

increment_mac() {
    local mac=$1
	local edge_wifi=$2

    # 将 MAC 地址转换为无分隔符的十六进制数
    local mac_hex=$(echo $mac | tr -d ':')

    # 将十六进制数转换为十进制数，加 1 后再转换回十六进制数
    local mac_dec=$((0x$mac_hex + $edge_wifi))
    local new_mac_hex=$(printf "%012X" $mac_dec)

    # 将新的十六进制数转换回 MAC 地址格式
    local new_mac=$(echo $new_mac_hex | sed 's/../&:/g;s/:$//')

    echo $new_mac
}

#wan_macaddr=$(uci get network.wan_dev.macaddr)
wan_macaddr=$(cat /sys/class/net/eth0/address | tr -d '\n')

start_instance() {
    local cfg="$1"

    local type
    config_get type "$cfg" TYPE

    case "$type" in
    edge)
        local enabled
        config_get_bool enabled "$cfg" 'enabled' '0'
        [ "$enabled" = "1" ] || return 1

        local masquerade tunname mode ipaddr prefix mtu encryption mcast link_mode edge_wifi pmtu header_encrypion id
        local supernode port second_supernode second_port
        local community key route
        config_get_bool masquerade "$cfg" 'masquerade' '0'
        config_get tunname "$cfg" 'tunname'
        config_get mode "$cfg" 'mode'
        config_get ipaddr "$cfg" 'ipaddr'
        config_get prefix "$cfg" 'prefix'
        config_get edge_wifi "$cfg" 'edge_wifi'
        config_get mtu "$cfg" 'mtu'
        config_get pmtu "$cfg" 'pmtu'
        config_get supernode "$cfg" 'supernode'
        config_get port "$cfg" 'port'
        config_get second_supernode "$cfg" 'second_supernode'
        config_get second_port "$cfg" 'second_port'
        config_get community "$cfg" 'community'
        config_get key "$cfg" 'key'
        config_get encryption "$cfg" 'encryption'
        config_get mcast "$cfg" 'mcast'
        config_get header_encrypion "$cfg" 'header_encrypion'
        config_get link_mode "$cfg" 'link_mode'
        config_get id "$cfg" 'id'
        config_get_bool route "$cfg" 'route' '0'

        local tunmac=$(increment_mac $wan_macaddr $edge_wifi)

        local address
        address="$ipaddr/$prefix"
        [ "$mode" != 'dhcp' ] || address='0.0.0.0'

        procd_open_instance "edge_$cfg"
        procd_set_param command /usr/bin/n2n-edge -f
        procd_append_param command -u 0 -g 0
        procd_append_param command -d "$tunname"
        procd_append_param command -m "$tunmac"
        procd_append_param command -a "$mode:$address"
        procd_append_param command -c "$community"
        procd_append_param command -l "$supernode:$port"
        [ -z "$key" ] || procd_append_param command -k "$key"
        [ -z "$mtu" ] || procd_append_param command -M "$mtu"
        [ -z "$second_supernode" -o -z "$second_port" ] || procd_append_param command -l "$second_supernode:$second_port"
        [ "$route" = "0" ] || procd_append_param command -r
        [ "$mcast" = "0" ] || procd_append_param command -E
	if [ "$header_encrypion" = "1" ];then
                procd_append_param command -H
                echo "$community" > /etc/n2n/"$id"_"$community"
                echo ".*" >> /etc/n2n/"$id"_"$community"	
	else
		echo "$community" > /etc/n2n/"$id"_"$community"
	fi
        [ "$pmtu" = "0" ] || procd_append_param command -D
        procd_append_param command "$link_mode"
        procd_append_param command "$encryption"

        procd_set_param stdout 1
        procd_set_param stderr 1
        procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
        procd_close_instance

        iptables -D FORWARD -i "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        iptables -D FORWARD -o "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        iptables -t nat -D POSTROUTING -o "$tunname" -j MASQUERADE -m comment --comment 'n2n edge net' 2>/dev/null

        iptables -I FORWARD -i "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        iptables -I FORWARD -o "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        [ "$masquerade" = "0" ] || iptables -t nat -I POSTROUTING -o "$tunname" -j MASQUERADE -m comment --comment 'n2n edge net' 2>/dev/null
    ;;
    supernode)
        local enabled community id
        config_get_bool enabled "$cfg" 'enabled' '0'
        [ "$enabled" = "1" ] || return 1

        local port subnet
        config_get port "$cfg" 'port'
        config_get subnet "$cfg" 'subnet'
        config_get community "$cfg" 'community'
        config_get id "$cfg" 'id'

        procd_open_instance "supernode_$cfg"
        procd_set_param command /usr/bin/n2n-supernode -f
	procd_append_param command -c /etc/n2n/"$id"_"$community"
        procd_append_param command -p "$port"
        #procd_append_param command -a "$subnet"

        procd_set_param stdout 1
        procd_set_param stderr 1
        procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
        procd_close_instance

        iptables -D INPUT -p udp --dport $port -j ACCEPT -m comment --comment 'n2n supernode port' 2>/dev/null
        iptables -I INPUT -p udp --dport $port -j ACCEPT -m comment --comment 'n2n supernode port' 2>/dev/null
    ;;
    route)
        local enabled
        config_get_bool enabled "$cfg" 'enabled' '0'
        [ "$enabled" = "1" ] || return 1

        local ip mask gw
        config_get ip "$cfg" 'ip'
        config_get mask "$cfg" 'mask'
        config_get gw "$cfg" 'gw'
        route add -net "$ip/$mask" gw "$gw"
    ;;
    esac
}

stop_instance() {
    local cfg="$1"

    local type
    config_get type "$cfg" TYPE

    case "$type" in
    edge)
        local tunname masquerade
        config_get tunname "$cfg" 'tunname'
        config_get_bool masquerade "$cfg" 'masquerade' '0'

        iptables -D FORWARD -i "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        iptables -D FORWARD -o "$tunname" -j ACCEPT -m comment --comment 'n2n edge eth' 2>/dev/null
        iptables -t nat -D POSTROUTING -o "$tunname" -j MASQUERADE -m comment --comment 'n2n edge net' 2>"/dev/null"
    ;;
    supernode)
        local port
        config_get port "$cfg" 'port'

        iptables -D INPUT -p udp --dport "$port" -j ACCEPT -m comment --comment 'n2n supernode port' 2>"/dev/null"
    ;;
    esac
}

start_service() {
    config_load 'n2n'
    config_foreach start_instance 'edge'
    config_foreach start_instance 'supernode'
    
    # ( sleep 2; config_foreach start_instance 'route'; ) &
}

stop_service() {
    config_load 'n2n'
    config_foreach stop_instance 'edge'
    config_foreach stop_instance 'supernode'
}

reload_service() {
    stop
    start
}

service_triggers() {
    procd_add_reload_trigger "n2n"
}
